/**
 * @file Persister.h
 * @brief Raft 持久化存储类定义
 * 
 * 负责 Raft 状态和快照的持久化存储管理
 * 提供线程安全的读写接口，确保数据持久性
 * 支持 Raft 状态和快照的独立管理
 */
#ifndef SKIP_LIST_ON_RAFT_PERSISTER_H
#define SKIP_LIST_ON_RAFT_PERSISTER_H
#include <fstream>
#include <mutex>

/**
 * @class Persister
 * @brief Raft 持久化存储管理器
 * 
 * 负责将 Raft 的关键状态（currentTerm、votedFor、log[]）和快照数据
 * 持久化到磁盘文件中，确保节点重启后能够正确恢复状态。
 * 
 * 主要功能：
 * - Raft 状态的读写（currentTerm、votedFor、日志条目）
 * - 快照数据的读写和管理
 * - 线程安全的并发访问控制
 * - 文件大小统计和管理
 */
class Persister {
 private:
  std::mutex m_mtx;                    ///< 互斥锁，保证线程安全
  std::string m_raftState;             ///< 内存中的 Raft 状态缓存
  std::string m_snapshot;              ///< 内存中的快照数据缓存
  
  /**
   * @brief Raft 状态文件名
   * 存储 currentTerm、votedFor 和日志条目等持久化状态
   */
  const std::string m_raftStateFileName;
  
  /**
   * @brief 快照文件名
   * 存储状态机快照数据，用于日志压缩
   */
  const std::string m_snapshotFileName;
  
  /**
   * @brief 保存 Raft 状态的输出流
   * 用于将 Raft 状态数据写入持久化文件
   */
  std::ofstream m_raftStateOutStream;
  
  /**
   * @brief 保存快照的输出流
   * 用于将快照数据写入持久化文件
   */
  std::ofstream m_snapshotOutStream;
  
  /**
   * @brief 保存 Raft 状态文件的大小
   * 避免每次都读取文件来获取具体的大小，提高性能
   */
  long long m_raftStateSize;

 public:
  /**
   * @brief 同时保存 Raft 状态和快照
   * @param raftstate Raft 状态的序列化数据
   * @param snapshot 快照的序列化数据
   */
  void Save(std::string raftstate, std::string snapshot);
  
  /**
   * @brief 读取快照数据
   * @return 快照的序列化数据，如果文件不存在则返回空字符串
   */
  std::string ReadSnapshot();
  
  /**
   * @brief 仅保存 Raft 状态
   * @param data Raft 状态的序列化数据
   */
  void SaveRaftState(const std::string& data);
  
  /**
   * @brief 获取 Raft 状态文件的大小
   * @return Raft 状态文件的字节数
   */
  long long RaftStateSize();
  
  /**
   * @brief 读取 Raft 状态数据
   * @return Raft 状态的序列化数据，如果文件不存在则返回空字符串
   */
  std::string ReadRaftState();
  
  /**
   * @brief 构造函数
   * @param me 节点 ID，用于生成唯一的文件名
   * 
   * 初始化持久化存储，创建对应的文件和输出流
   */
  explicit Persister(int me);
  
  /**
   * @brief 析构函数
   * 关闭所有打开的文件流，清理资源
   */
  ~Persister();

 private:
  /**
   * @brief 清空 Raft 状态文件
   * 删除现有的 Raft 状态数据并重置大小计数器
   */
  void clearRaftState();
  
  /**
   * @brief 清空快照文件
   * 删除现有的快照数据
   */
  void clearSnapshot();
  
  /**
   * @brief 同时清空 Raft 状态和快照文件
   * 删除所有持久化数据
   */
  void clearRaftStateAndSnapshot();
};

#endif  // SKIP_LIST_ON_RAFT_PERSISTER_H
